home *** CD-ROM | disk | FTP | other *** search
/ Personal Computer World 2009 February / PCWFEB09.iso / Software / Resources / Chat & Communication / Digsby build 37 / digsby_setup.exe / lib / util / net.pyo (.txt) < prev    next >
Encoding:
Python Compiled Bytecode  |  2008-10-13  |  33.1 KB  |  1,250 lines

  1. # Source Generated with Decompyle++
  2. # File: in.pyo (Python 2.5)
  3.  
  4. from __future__ import with_statement
  5. import sys
  6. import traceback
  7. import re
  8. import struct
  9. import logging
  10. import socks
  11. import socket
  12. import asynchat
  13. import urllib
  14. import urllib2
  15. import urlparse
  16. import httplib
  17. import httplib2
  18. import cookielib
  19. from httplib import HTTPConnection
  20. from httplib import NotConnected
  21. import primitives
  22. import proxy_settings
  23. from Events import EventMixin
  24. from callbacks import callsback
  25. log = logging.getLogger('util.net')
  26. default_chunksize = 4096
  27.  
  28. def get_ips_s(hostname = ''):
  29.     if not hostname:
  30.         pass
  31.     return socket.gethostbyname_ex(socket.gethostname())[2]
  32.  
  33.  
  34. def get_ips(hostname = ''):
  35.     return [ socket.inet_aton(ip) for ip in get_ips_s(hostname) ]
  36.  
  37. myips = get_ips
  38.  
  39. def myip():
  40.     return myips()[0]
  41.  
  42.  
  43. def ip_from_bytes(bytes):
  44.     return socket.inet_ntoa(bytes)
  45.  
  46.  
  47. class FileChunker:
  48.     
  49.     def __init__(self, fileobj, chunksize = default_chunksize, close_when_done = False, progress_cb = (lambda bytes: pass), bytecounter = None):
  50.         self.fileobj = fileobj
  51.         self.chunksize = chunksize
  52.         self.close_when_done = close_when_done
  53.         if bytecounter is None:
  54.             bytecounter = fileobj.tell
  55.         
  56.         self.total = bytecounter()
  57.         self.progress_cb = progress_cb
  58.         self.cancelled = False
  59.  
  60.     
  61.     def more(self):
  62.         
  63.         try:
  64.             data_read = self.fileobj.read(self.chunksize)
  65.         except ValueError:
  66.             
  67.             try:
  68.                 self.fileobj.close()
  69.             except:
  70.                 pass
  71.  
  72.             return ''
  73.  
  74.         sz = len(data_read)
  75.         if sz == 0 and self.close_when_done:
  76.             self.fileobj.close()
  77.         
  78.         self.total += sz
  79.         self.progress_cb(self.total)
  80.         return data_read
  81.  
  82.     
  83.     def tofile(cls, sourcefile, outfile, progress_callback = (lambda : pass), bytecounter = None):
  84.         gen = cls.tofile_gen(sourcefile, outfile, progress_callback, bytecounter)
  85.         gen.next()
  86.         
  87.         try:
  88.             gen.next()
  89.         except StopIteration:
  90.             pass
  91.  
  92.  
  93.     tofile = classmethod(tofile)
  94.     
  95.     def tofile_gen(cls, sourcefile, outfile, progress_callback = (lambda : pass), bytecounter = None):
  96.         fc = cls(sourcefile, close_when_done = True, bytecounter = bytecounter)
  97.         yield fc
  98.         chunk = fc.more()
  99.         bytes_written = 0
  100.         write = outfile.write
  101.         tell = outfile.tell
  102.         more = fc.more
  103.         while chunk and not (fc.cancelled):
  104.             write(chunk)
  105.             bytes_written += len(chunk)
  106.             progress_callback(tell())
  107.             chunk = more()
  108.         outfile.close()
  109.  
  110.     tofile_gen = classmethod(tofile_gen)
  111.  
  112.  
  113. def httpjoin(base, path, keepquery = False):
  114.     if path.startswith('http'):
  115.         return path
  116.     else:
  117.         joined = urlparse.urljoin(base, path)
  118.         if not keepquery:
  119.             parsed = list(urlparse.urlparse(joined))
  120.             parsed[4] = ''
  121.             return urlparse.urlunparse(parsed)
  122.         else:
  123.             return joined
  124.  
  125.  
  126. class UrlQuery(str):
  127.     
  128.     def parse(cls, url, parse_query = True):
  129.         (scheme, netloc, path, params, query, fragment) = urlparse.urlparse(url)
  130.         if parse_query:
  131.             querymap = { }
  132.             for elem in query.split('&'):
  133.                 (key, value) = None if '=' in elem else (elem, True)
  134.                 querymap[key] = value
  135.             
  136.             query = querymap
  137.         
  138.         return dict(scheme = scheme, netloc = netloc, path = path, params = params, query = query, fragment = fragment)
  139.  
  140.     parse = classmethod(parse)
  141.     
  142.     def __new__(cls, link, d = { }, **kwargs):
  143.         if link.endswith('?'):
  144.             link = link[:-1]
  145.         
  146.         if '?' in link:
  147.             joiner = '&'
  148.         else:
  149.             joiner = '?'
  150.         return str.__new__(cls, ''.join([
  151.             link,
  152.             joiner,
  153.             WebFormData(d = d, **kwargs)]))
  154.  
  155.  
  156.  
  157. class WebFormData(str):
  158.     
  159.     def __new__(cls, d = { }, **kwargs):
  160.         if d and kwargs:
  161.             kwargs.update(d)
  162.         elif not kwargs:
  163.             pass
  164.         kwargs = d
  165.         base = urllib.urlencode(kwargs)
  166.         return str.__new__(cls, base)
  167.  
  168.  
  169.  
  170. def int_to_ip(s, byteorder = '<'):
  171.     return '.'.join((lambda .0: for c in .0:
  172. str(ord(c)))(struct.pack(byteorder + 'I', int(s))))
  173.  
  174. spacify_pattern = re.compile('( {2,})')
  175.  
  176. def spacify_repl(m):
  177.     l = len(m.group())
  178.     if l == 2:
  179.         return '  '
  180.     else:
  181.         return ' ' + ''.join([
  182.             ' '] * (l - 2)) + ' '
  183.  
  184.  
  185. def spacify(s):
  186.     return spacify_pattern.sub(spacify_repl, s)
  187.  
  188. urlregex = re.compile("([A-Za-z][A-Za-z0-9+.-]{1,120}:[A-Za-z0-9/](([A-Za-z0-9$_.+!*,;/?:@&~=-])|%[A-Fa-f0-9]{2}){1,333}(#([a-zA-Z0-9][a-zA-Z0-9$_.+!*,;/?:@&~=%-']{0,1000}))?)[^\\. <]")
  189. TLDs = [
  190.     'arpa',
  191.     'root',
  192.     'aero',
  193.     'asia',
  194.     'biz',
  195.     'com',
  196.     'coop',
  197.     'edu',
  198.     'gov',
  199.     'info',
  200.     'int',
  201.     'museum',
  202.     'name',
  203.     'net',
  204.     'org',
  205.     'pro',
  206.     'ac',
  207.     'ad',
  208.     'ae',
  209.     'af',
  210.     'ag',
  211.     'ai',
  212.     'al',
  213.     'am',
  214.     'an',
  215.     'ao',
  216.     'aq',
  217.     'ar',
  218.     'as',
  219.     'at',
  220.     'au',
  221.     'aw',
  222.     'ax',
  223.     'az',
  224.     'ba',
  225.     'bb',
  226.     'bd',
  227.     'be',
  228.     'bf',
  229.     'bg',
  230.     'bh',
  231.     'bi',
  232.     'bj',
  233.     'bm',
  234.     'bn',
  235.     'bo',
  236.     'br',
  237.     'bs',
  238.     'bt',
  239.     'bv',
  240.     'bw',
  241.     'by',
  242.     'bz',
  243.     'ca',
  244.     'cc',
  245.     'cd',
  246.     'cf',
  247.     'cg',
  248.     'ch',
  249.     'ci',
  250.     'ck',
  251.     'cl',
  252.     'cm',
  253.     'cn',
  254.     'co',
  255.     'cr',
  256.     'cu',
  257.     'cv',
  258.     'cx',
  259.     'cy',
  260.     'cz',
  261.     'de',
  262.     'dj',
  263.     'dk',
  264.     'dm',
  265.     'do',
  266.     'dz',
  267.     'ec',
  268.     'ee',
  269.     'eg',
  270.     'er',
  271.     'es',
  272.     'et',
  273.     'eu',
  274.     'fi',
  275.     'fj',
  276.     'fk',
  277.     'fm',
  278.     'fo',
  279.     'fr',
  280.     'ga',
  281.     'gb',
  282.     'gd',
  283.     'ge',
  284.     'gf',
  285.     'gg',
  286.     'gh',
  287.     'gi',
  288.     'gl',
  289.     'gm',
  290.     'gn',
  291.     'gp',
  292.     'gq',
  293.     'gr',
  294.     'gs',
  295.     'gt',
  296.     'gu',
  297.     'gw',
  298.     'gy',
  299.     'hk',
  300.     'hm',
  301.     'hn',
  302.     'hr',
  303.     'ht',
  304.     'hu',
  305.     'id',
  306.     'ie',
  307.     'il',
  308.     'im',
  309.     'in',
  310.     'io',
  311.     'iq',
  312.     'ir',
  313.     'is',
  314.     'it',
  315.     'je',
  316.     'jm',
  317.     'jo',
  318.     'jp',
  319.     'ke',
  320.     'kg',
  321.     'kh',
  322.     'ki',
  323.     'km',
  324.     'kn',
  325.     'kp',
  326.     'kr',
  327.     'kw',
  328.     'ky',
  329.     'kz',
  330.     'la',
  331.     'lb',
  332.     'lc',
  333.     'li',
  334.     'lk',
  335.     'lr',
  336.     'ls',
  337.     'lt',
  338.     'lu',
  339.     'lv',
  340.     'ly',
  341.     'ma',
  342.     'mc',
  343.     'md',
  344.     'me',
  345.     'mg',
  346.     'mh',
  347.     'mk',
  348.     'ml',
  349.     'mm',
  350.     'mn',
  351.     'mo',
  352.     'mp',
  353.     'mq',
  354.     'mr',
  355.     'ms',
  356.     'mt',
  357.     'mu',
  358.     'mv',
  359.     'mw',
  360.     'mx',
  361.     'my',
  362.     'mz',
  363.     'na',
  364.     'nc',
  365.     'ne',
  366.     'nf',
  367.     'ng',
  368.     'ni',
  369.     'nl',
  370.     'no',
  371.     'np',
  372.     'nr',
  373.     'nu',
  374.     'nz',
  375.     'om',
  376.     'pa',
  377.     'pe',
  378.     'pf',
  379.     'pg',
  380.     'ph',
  381.     'pk',
  382.     'pl',
  383.     'pm',
  384.     'pn',
  385.     'pr',
  386.     'ps',
  387.     'pt',
  388.     'pw',
  389.     'py',
  390.     'qa',
  391.     're',
  392.     'ro',
  393.     'rs',
  394.     'ru',
  395.     'rw',
  396.     'sa',
  397.     'sb',
  398.     'sc',
  399.     'sd',
  400.     'se',
  401.     'sg',
  402.     'sh',
  403.     'si',
  404.     'sj',
  405.     'sk',
  406.     'sl',
  407.     'sm',
  408.     'sn',
  409.     'so',
  410.     'sr',
  411.     'st',
  412.     'su',
  413.     'sv',
  414.     'sy',
  415.     'sz',
  416.     'tc',
  417.     'td',
  418.     'tf',
  419.     'tg',
  420.     'th',
  421.     'tj',
  422.     'tk',
  423.     'tl',
  424.     'tm',
  425.     'tn',
  426.     'to',
  427.     'tp',
  428.     'tr',
  429.     'tt',
  430.     'tv',
  431.     'tw',
  432.     'tz',
  433.     'ua',
  434.     'ug',
  435.     'uk',
  436.     'um',
  437.     'us',
  438.     'uy',
  439.     'uz',
  440.     'va',
  441.     'vc',
  442.     've',
  443.     'vg',
  444.     'vi',
  445.     'vn',
  446.     'vu',
  447.     'wf',
  448.     'ws',
  449.     'ye',
  450.     'yt',
  451.     'yu',
  452.     'za',
  453.     'zm',
  454.     'zw']
  455. domains = '(?:%s)' % '|'.join(TLDs)
  456. email_regex_string = '(([a-zA-Z0-9_][a-zA-Z0-9_\\-\\.]*)(\\+[a-zA-Z0-9_\\-\\.]+)?@(([a-zA-Z0-9\\-_]+\\.?)*[a-zA-Z]{1,4}))'
  457. email_regex = re.compile(email_regex_string)
  458. email_wholestring_regex = re.compile('^' + email_regex_string + '$')
  459. is_email = primitives.ischeck((lambda s: bool(email_wholestring_regex.match(s))))
  460.  
  461. class EmailAddress(tuple):
  462.     
  463.     def __new__(cls, addr, default_domain = sentinel):
  464.         
  465.         try:
  466.             (name, label, domain) = parse_email(addr)
  467.         except:
  468.             if default_domain is sentinel:
  469.                 raise 
  470.             else:
  471.                 (name, label, domain) = parse_email(addr + '@' + default_domain)
  472.  
  473.         return tuple.__new__(cls, (name, label, domain))
  474.  
  475.     
  476.     def name(self):
  477.         return self[0]
  478.  
  479.     name = property(name)
  480.     
  481.     def label(self):
  482.         return self[1]
  483.  
  484.     label = property(label)
  485.     
  486.     def domain(self):
  487.         return self[2]
  488.  
  489.     domain = property(domain)
  490.     
  491.     def __str__(self):
  492.         if self.label:
  493.             return '%s+%s@%s' % self
  494.         else:
  495.             return '%s@%s' % (self.name, self.domain)
  496.  
  497.     
  498.     def __repr__(self):
  499.         return '<EmailAddress %s>' % (self,)
  500.  
  501.  
  502.  
  503. def parse_email(s):
  504.     match = email_wholestring_regex.match(s)
  505.     (wholething, user, lbl, dom, __) = match.groups()
  506.     if lbl:
  507.         lbl = lbl.strip('+')
  508.     else:
  509.         lbl = ''
  510.     return (user, lbl, dom)
  511.  
  512. protocols = 'ftp|https?|gopher|msnim|icq|telnet|nntp|aim|file|svn|svn+(?:\\w)+'
  513. linkify_url_pattern = re.compile('(?=[a-zA-Z0-9])                          # Must start correctly\n      ((?:                                        # Match the leading part (proto://hostname, or just hostname)\n          (?P<protocol>\n          (?:%s)                                  #     protocol\n          ://                                     #     ://\n          (?:                                     #     Optional \'username:password@\'\n              \\w+                                 #         username\n              (?::\\w+)?                           #         optional :password\n              @                                   #         @\n          )?)?                                    #\n          (?P<hostname>[-\\w]+(?:\\.\\w[-\\w]*)*)     #     hostname (sub.example.com)\n      )?                                          #\n      (?::\\d+)?                                   # Optional port number\n      (?:                                         # Rest of the URL, optional\n          /?                                      #     Start with \'/\'\n          [^.!,?;:"<>\\[\\]{}\\s\\x7F-\\xFF]*          #     Can\'t start with these\n          (?:                                     #\n              [.!,?;:]+                           #     One or more of these\n              [^.!,?;:"<>\\[\\]{}\\s\\x7F-\\xFF]+      #     Can\'t finish with these\n              #\'"                                 #     # or \' or "\n          )*                                      #\n      )?)                                         #\n   ' % protocols, re.VERBOSE)
  514.  
  515. def isurl(text):
  516.     m = linkify_url_pattern.match(text)
  517.     if not m:
  518.         return False
  519.     
  520.     protocol = m.group('protocol')
  521.     host = m.group('hostname')
  522.     if host is not None:
  523.         if protocol is None:
  524.             myTLDs = None if '.' in host else [
  525.                 host]
  526.             if len(myTLDs) < 2 or myTLDs[-1] not in TLDs:
  527.                 return False
  528.             
  529.         
  530.     
  531.     return True
  532.  
  533.  
  534. def _dolinkify(text):
  535.     
  536.     def repl(m):
  537.         protocol = m.group('protocol')
  538.         host = m.group('hostname')
  539.         url = m.group()
  540.         after = ''
  541.         if url.endswith(')') and '(' not in url:
  542.             url = url[:-1]
  543.             after = ')'
  544.         
  545.         if host is not None:
  546.             if protocol is None:
  547.                 myTLDs = None if '.' in host else [
  548.                     host]
  549.                 if len(myTLDs) < 2 or myTLDs[-1] not in TLDs:
  550.                     return url + after
  551.                 
  552.             
  553.         
  554.         href = None if protocol is None else url
  555.         return '<a href="%s">%s</a>' % (href, url) + after
  556.  
  557.     text = linkify_url_pattern.sub(repl, text)
  558.     return text
  559.  
  560.  
  561. def linkify(text):
  562.     if not re.search('<.*>', text):
  563.         return _dolinkify(text)
  564.     else:
  565.         lines = []
  566.         for line in re.split('(<.*?>)', text):
  567.             if not re.match('<.*?>', line):
  568.                 line = _dolinkify(line)
  569.             
  570.             lines.append(line)
  571.         
  572.         return ''.join(lines)
  573.  
  574.  
  575. class QueueableMixin(object):
  576.     
  577.     def __init__(self):
  578.         object.__init__(self)
  579.         self._on_queue = False
  580.  
  581.     
  582.     def queue(self):
  583.         if not self._on_queue:
  584.             self._queue()
  585.             self._on_queue = True
  586.         
  587.  
  588.     
  589.     def unqueue(self):
  590.         if self._on_queue:
  591.             self._unqueue()
  592.             self._on_queue = False
  593.         
  594.  
  595.  
  596.  
  597. class ProducerQueuable(QueueableMixin):
  598.     
  599.     def __init__(self, sck):
  600.         QueueableMixin.__init__(self)
  601.         self.sck = sck
  602.  
  603.     
  604.     def _queue(self):
  605.         self.sck.push_with_producer(self)
  606.  
  607.     
  608.     def _unqueue(self):
  609.         
  610.         try:
  611.             self.sck.producer_fifo.remove(self)
  612.         except ValueError:
  613.             pass
  614.  
  615.  
  616.  
  617.  
  618. class RoundRobinProducer(ProducerQueuable):
  619.     
  620.     def __init__(self, sck):
  621.         ProducerQueuable.__init__(self, sck)
  622.         self.list = []
  623.  
  624.     
  625.     def add(self, prod):
  626.         
  627.         try:
  628.             if not callable(prod.more):
  629.                 raise AssertionError('Producers must have a "more" method')
  630.         except:
  631.             traceback.print_exc()
  632.             raise 
  633.  
  634.         self.unqueue()
  635.         self.list.append(prod)
  636.         self.queue()
  637.  
  638.     
  639.     def more(self):
  640.         self._on_queue = True
  641.         d = None
  642.         l = self.list
  643.         prod = None
  644.         while not d and l:
  645.             prod = l.pop(0)
  646.             d = prod.more()
  647.         if d:
  648.             l.append(prod)
  649.         else:
  650.             self.unqueue()
  651.             if self.list:
  652.                 self.queue()
  653.             
  654.         return d
  655.  
  656.  
  657.  
  658. class PriorityProducer(ProducerQueuable):
  659.     
  660.     def __init__(self, sck):
  661.         ProducerQueuable.__init__(self, sck)
  662.         self.high = []
  663.         self.mid = []
  664.         self.low = []
  665.  
  666.     
  667.     def add(self, prod, pri = 'mid'):
  668.         self.unqueue()
  669.         getattr(self, pri).append(prod)
  670.         self.queue()
  671.  
  672.     
  673.     def more(self):
  674.         self._on_queue = True
  675.         d = None
  676.         for l in (self.high, self.mid, self.low):
  677.             if not l:
  678.                 continue
  679.             
  680.             while not d and l:
  681.                 prod = l.pop(0)
  682.                 d = prod.more()
  683.             if d:
  684.                 l.insert(0, prod)
  685.                 break
  686.                 continue
  687.         
  688.         return d
  689.  
  690.  
  691.  
  692. class HTTPConnProgress(HTTPConnection):
  693.     
  694.     def send_file_cb(self, fileobj, progress_cb, blocksize = default_chunksize, progressDelta = 0):
  695.         if self.sock is None:
  696.             if self.auto_open:
  697.                 self.connect()
  698.             else:
  699.                 raise NotConnected()
  700.         
  701.         if self.debuglevel > 0:
  702.             print 'sending contents of', fileobj
  703.         
  704.         
  705.         try:
  706.             read = fileobj.read
  707.             sendall = self.sock.sendall
  708.             chunk = read(blocksize)
  709.             total = 0
  710.             while chunk:
  711.                 total += len(chunk)
  712.                 sendall(chunk)
  713.                 progress_cb(total - progressDelta)
  714.                 chunk = read(blocksize)
  715.         except socket.error:
  716.             v = None
  717.             if v[0] == 32:
  718.                 self.close()
  719.             
  720.             raise 
  721.  
  722.  
  723.  
  724.  
  725. class SocketEventMixin(EventMixin):
  726.     events = EventMixin.events | set(('connected', 'connection_failed', 'socket_error', 'socket_closed'))
  727.     
  728.     def post_connect_error(self, e = None):
  729.         self.event('socket_error')
  730.         self.post_connect_disconnect()
  731.  
  732.     
  733.     def post_connect_expt(self):
  734.         self.event('socket_error')
  735.         self.post_connect_disconnect()
  736.  
  737.     
  738.     def post_connect_disconnect(self):
  739.         self.close()
  740.         self.event('socket_closed')
  741.  
  742.     
  743.     def post_connect_close(self):
  744.         self.close()
  745.         self.event('socket_closed')
  746.  
  747.     
  748.     def reassign(self):
  749.         self.handle_expt = self.post_connect_expt
  750.         self.handle_error = self.post_connect_error
  751.         self.handle_close = self.post_connect_close
  752.         self.do_disconnect = self.post_connect_disconnect
  753.  
  754.  
  755.  
  756. def build_cookie(name, value, version = 0, domain = sentinel, port = sentinel, path = sentinel, secure = False, expires = None, discard = False, comment = None, comment_url = None, rest = {
  757.     'httponly': None }, rfc2109 = False):
  758.     if domain is sentinel:
  759.         domain = None
  760.         domain_specified = False
  761.         domain_initial_dot = False
  762.     else:
  763.         domain_specified = True
  764.         domain_initial_dot = domain.startswith('.')
  765.     if port is sentinel:
  766.         port = None
  767.         port_specified = False
  768.     else:
  769.         port_specified = True
  770.     if path is sentinel:
  771.         path = None
  772.         path_specified = False
  773.     else:
  774.         path_specified = True
  775.     return cookielib.Cookie(**locals())
  776.  
  777.  
  778. def GetSocketType():
  779.     d = GetProxyInfo()
  780.     if d:
  781.         return socks.socksocket
  782.     else:
  783.         return socket.socket
  784.  
  785. NONE = 'NONPROX'
  786. SYSDEFAULT = 'SYSPROX'
  787. CUSTOM = 'SETPROX'
  788.  
  789. def GetProxyInfo():
  790.     ps = proxy_settings
  791.     
  792.     try:
  793.         pd = ps.get_proxy_dict()
  794.     except Exception:
  795.         e = None
  796.         print >>sys.stderr, 'No proxies because: %r' % e
  797.         pd = { }
  798.  
  799.     get = pd.get
  800.     proxytype = get('proxytype')
  801.     port = get('port')
  802.     
  803.     try:
  804.         port = int(port)
  805.     except:
  806.         port = None
  807.  
  808.     addr = get('addr')
  809.     username = get('username')
  810.     password = get('password')
  811.     override = get('override')
  812.     
  813.     try:
  814.         override = int(override)
  815.     except:
  816.         if override not in (SYSDEFAULT, CUSTOM, NONE):
  817.             override = SYSDEFAULT
  818.         
  819.  
  820.     if override:
  821.         override = CUSTOM
  822.     else:
  823.         override = SYSDEFAULT
  824.     if override == NONE:
  825.         return { }
  826.     elif override == SYSDEFAULT:
  827.         px = urllib._getproxies()
  828.         if not px:
  829.             return { }
  830.         
  831.         url = px.get('http', None)
  832.         if url is None:
  833.             return { }
  834.         
  835.         url = urlparse.urlparse(url)
  836.         if not url.hostname:
  837.             pass
  838.         addr = ''
  839.         if not addr:
  840.             return { }
  841.         
  842.         if not url.port:
  843.             pass
  844.         port = 80
  845.         if not url.username and username:
  846.             pass
  847.         username = None
  848.         if not url.password and password:
  849.             pass
  850.         password = None
  851.         proxytype = 'http'
  852.     
  853.     if all((type, port, addr)):
  854.         proxytype = getattr(socks, ('proxy_type_%s' % proxytype).upper(), None)
  855.         return dict(addr = addr, port = port, username = username, password = password, proxytype = proxytype)
  856.     else:
  857.         return { }
  858.  
  859.  
  860. def GetProxyInfoHttp2():
  861.     i = GetProxyInfo()
  862.     if not i:
  863.         return None
  864.     
  865.     return httplib2.ProxyInfo(proxy_type = i['proxytype'], proxy_host = i['addr'], proxy_port = i['port'], proxy_user = i['username'], proxy_pass = i['password'], proxy_rdns = True)
  866.  
  867.  
  868. def getproxies_digsby():
  869.     pinfo = GetProxyInfo()
  870.     proxies = { }
  871.     if pinfo.get('username', None) and pinfo.get('password', None):
  872.         unpw = '%s:%s@' % (pinfo['username'], pinfo['password'])
  873.     else:
  874.         unpw = ''
  875.     if pinfo.get('port', None):
  876.         port = ':' + str(pinfo['port'])
  877.     else:
  878.         port = ''
  879.     host = pinfo.get('addr', None)
  880.     if not host:
  881.         return proxies
  882.     
  883.     all = unpw + host + port
  884.     proxies = urllib.OneProxy()
  885.     proxies._proxyServer = all
  886.     if pinfo['proxytype'] != socks.PROXY_TYPE_HTTP:
  887.         proxy_url = None % 'socks%d://' if pinfo['proxytype'] == socks.PROXY_TYPE_SOCKS4 else 5 + all
  888.         return dict(socks = proxy_url, http = proxy_url, https = proxy_url)
  889.     
  890.     proxies['https'] = 'http://' + all
  891.     proxies['http'] = 'http://' + all
  892.     proxies['ftp'] = 'http://' + all
  893.     return proxies
  894.  
  895.  
  896. class SocksProxyHandler(urllib2.ProxyHandler):
  897.     handler_order = 100
  898.     
  899.     def proxy_open(self, req, type):
  900.         
  901.         try:
  902.             req._proxied
  903.         except AttributeError:
  904.             proxyinfo = self.proxies.get(type, '')
  905.             proxytype = urllib2._parse_proxy(proxyinfo)[0]
  906.             if proxytype is None:
  907.                 req._proxied = False
  908.                 return urllib2.ProxyHandler.proxy_open(self, req, type)
  909.             else:
  910.                 req._proxytype = proxytype
  911.                 req._proxied = True
  912.                 if proxytype == 'http' and type != 'https':
  913.                     return urllib2.ProxyHandler.proxy_open(self, req, type)
  914.                 else:
  915.                     return None
  916.         except:
  917.             proxytype is None
  918.  
  919.         return None
  920.  
  921.     
  922.     def socks4_open(self, req):
  923.         return self.socks_open(req, 4)
  924.  
  925.     
  926.     def socks5_open(self, req):
  927.         return self.socks_open(req, 5)
  928.  
  929.     
  930.     def socks_open(self, req, sockstype):
  931.         (orig_url_type, __, __, orighostport) = urllib2._parse_proxy(req.get_full_url())
  932.         req.set_proxy(orighostport, orig_url_type)
  933.         endpoint = req.get_host()
  934.         if ':' in endpoint:
  935.             (host, port) = endpoint.rsplit(':', 1)
  936.             port = int(port)
  937.         else:
  938.             host = endpoint
  939.             port = 80
  940.         req._proxied = True
  941.         return self.parent.open(req)
  942.  
  943.  
  944. if hasattr(httplib, 'HTTPS'):
  945.     
  946.     class SocksHttpsOpener(urllib2.HTTPSHandler):
  947.         handler_order = 101
  948.         
  949.         def https_open(self, req):
  950.             if getattr(req, '_proxied', False) and getattr(req, '_proxytype', None) is not None:
  951.                 return urllib2.HTTPSHandler.do_open(self, SocksHttpsConnection, req)
  952.             else:
  953.                 return urllib2.HTTPSHandler.https_open(self, req)
  954.  
  955.  
  956.     
  957.     class SocksHttpsConnection(httplib.HTTPSConnection):
  958.         _sockettype = socks.socksocket
  959.         
  960.         def connect(self):
  961.             pd = urllib.getproxies().get('https', None)
  962.             if pd is None:
  963.                 sockstype = ''
  964.             else:
  965.                 (sockstype, user, password, hostport) = urllib2._parse_proxy(pd)
  966.             (host, port) = hostport.rsplit(':', 1)
  967.             port = int(port)
  968.             sock = self._sockettype(socket.AF_INET, socket.SOCK_STREAM)
  969.             sock.setproxy(proxytype = getattr(socks, 'PROXY_TYPE_%s' % sockstype.upper()), addr = host, port = port, rdns = True, username = user, password = password)
  970.             sock.connect((self.host, self.port))
  971.             ssl = socket.ssl(sock, self.key_file, self.cert_file)
  972.             self.sock = httplib.FakeSocket(sock, ssl)
  973.  
  974.  
  975.  
  976.  
  977. class SocksHttpOpener(urllib2.HTTPHandler):
  978.     handler_order = 101
  979.     
  980.     def http_open(self, req):
  981.         proxytype = getattr(req, '_proxytype', None)
  982.         if getattr(req, '_proxied', False) and proxytype not in ('http', None):
  983.             return urllib2.HTTPHandler.do_open(self, SocksConnection, req)
  984.         else:
  985.             return urllib2.HTTPHandler.http_open(self, req)
  986.  
  987.  
  988.  
  989. class SocksConnection(httplib.HTTPConnection):
  990.     _sockettype = socks.socksocket
  991.     
  992.     def connect(self):
  993.         pd = urllib.getproxies().get('http', None)
  994.         if pd is None:
  995.             sockstype = ''
  996.         else:
  997.             (sockstype, user, password, hostport) = urllib2._parse_proxy(pd)
  998.         if 'socks' not in sockstype:
  999.             return httplib.HTTPConnection.connect(self)
  1000.         
  1001.         (host, port) = hostport.rsplit(':', 1)
  1002.         port = int(port)
  1003.         for res in socket.getaddrinfo(self.host, self.port, 0, socket.SOCK_STREAM):
  1004.             (af, socktype, proto, canonname, sa) = res
  1005.             
  1006.             try:
  1007.                 self.sock = self._sockettype(af, socktype, proto)
  1008.                 self.sock.setproxy(proxytype = getattr(socks, 'PROXY_TYPE_%s' % sockstype.upper()), addr = host, port = port, rdns = False, username = user, password = password)
  1009.                 if self.debuglevel > 0:
  1010.                     print 'connect: (%s, %s)' % (self.host, self.port)
  1011.                 
  1012.                 self.sock.connect(sa)
  1013.             except socket.error:
  1014.                 msg = None
  1015.                 if self.debuglevel > 0:
  1016.                     print 'connect fail:', (self.host, self.port)
  1017.                 
  1018.                 if self.sock:
  1019.                     self.sock.close()
  1020.                 
  1021.                 self.sock = None
  1022.                 continue
  1023.  
  1024.         
  1025.         if not self.sock:
  1026.             raise socket.error, msg
  1027.         
  1028.  
  1029.  
  1030.  
  1031. class DigsbyHttpProxyPasswordManager(urllib2.HTTPPasswordMgr):
  1032.     
  1033.     def find_user_password(self, realm, uri):
  1034.         pi = GetProxyInfo()
  1035.         if not pi['username']:
  1036.             pass
  1037.         if not pi['password']:
  1038.             pass
  1039.         return (None, None)
  1040.  
  1041.  
  1042. if not hasattr(urllib, '_getproxies'):
  1043.     urllib._getproxies = urllib.getproxies
  1044.     urllib.getproxies = getproxies_digsby
  1045.     urllib2.UnknownHandler.handler_order = sys.maxint
  1046.     urllib2.ProxyDigestAuthHandler.__bases__ = urllib2.ProxyDigestAuthHandler.__bases__[::-1]
  1047.     urllib2.ProxyBasicAuthHandler.handler_order = 499
  1048.     httplib2.ProxyInfo.get_default_proxy = staticmethod(GetProxyInfoHttp2)
  1049.  
  1050.  
  1051. def GetDefaultHandlers():
  1052.     handlers = [
  1053.         SocksProxyHandler,
  1054.         SocksHttpOpener]
  1055.     httpsopener = globals().get('SocksHttpsOpener', None)
  1056.     if httpsopener is not None:
  1057.         handlers.append(httpsopener)
  1058.     
  1059.     pwdmgr = DigsbyHttpProxyPasswordManager()
  1060.     for auth_handler_type in (urllib2.ProxyBasicAuthHandler, urllib2.ProxyDigestAuthHandler):
  1061.         handlers.append(auth_handler_type(pwdmgr))
  1062.     
  1063.     return handlers
  1064.  
  1065.  
  1066. def build_opener(*a, **k):
  1067.     if 'default_classes' not in k:
  1068.         k['default_classes'] = GetDefaultHandlers()
  1069.     
  1070.     return urllib2.build_opener(*a, **k)
  1071.  
  1072. opener = urllib2.build_opener(*GetDefaultHandlers())
  1073. urllib2.install_opener(opener)
  1074. _hostprog = re.compile('^//([^/?]*)(.*)$')
  1075.  
  1076. def splithost(url):
  1077.     match = _hostprog.match(url)
  1078.     if match:
  1079.         groups = match.group(1, 2)
  1080.         if groups[0] == '':
  1081.             return (groups[0], '/' + groups[1])
  1082.         else:
  1083.             return groups
  1084.     
  1085.     return (None, url)
  1086.  
  1087. urllib.splithost = urllib2.splithost = splithost
  1088.  
  1089. def httpok(_code):
  1090.     return getattr(_code, 'status', _code) // 100 == 2
  1091.  
  1092.  
  1093. class CallbackProducerMixin(object):
  1094.     
  1095.     def __init__(self):
  1096.         bases = self.__class__.__bases__
  1097.         found_self = False
  1098.         self._siblingClass = None
  1099.         for base in bases:
  1100.             if base is CallbackProducerMixin:
  1101.                 found_self = True
  1102.                 continue
  1103.             if hasattr(base, 'more') and found_self:
  1104.                 self._siblingClass = base
  1105.                 break
  1106.                 continue
  1107.         
  1108.         if self._siblingClass is None:
  1109.             raise AssertionError("This mix-in requires there is a sibling class with a 'more' method. Additionally, CallbackProducerMixin must be *before* that class in the inheritance list (for method resolution reasons).")
  1110.         
  1111.  
  1112.     
  1113.     def set_callback(self, callback = None):
  1114.         self._callback = callback
  1115.  
  1116.     set_callback = callsback(set_callback)
  1117.     
  1118.     def more(self):
  1119.         if not hasattr(self, '_siblingClass'):
  1120.             result = ''
  1121.         else:
  1122.             result = self._siblingClass.more(self)
  1123.         if result == '':
  1124.             if getattr(self, '_callback', None) is not None:
  1125.                 self._callback.success()
  1126.             
  1127.             if getattr(self, '_callback', None) is not None:
  1128.                 del self._callback
  1129.             
  1130.         
  1131.         return result
  1132.  
  1133.  
  1134.  
  1135. class SimpleCallbackProducer(CallbackProducerMixin, asynchat.simple_producer):
  1136.     
  1137.     def __init__(self, data):
  1138.         asynchat.simple_producer.__init__(self, data)
  1139.         CallbackProducerMixin.__init__(self)
  1140.  
  1141.  
  1142.  
  1143. def _fifo_remove(self, val):
  1144.     
  1145.     try:
  1146.         self.list.remove(val)
  1147.     except Exception:
  1148.         return False
  1149.  
  1150.     return True
  1151.  
  1152. asynchat.fifo.remove = _fifo_remove
  1153.  
  1154. def producer_cb(data, callback = None):
  1155.     prod = SimpleCallbackProducer(data)
  1156.     prod.set_callback(callback = callback)
  1157.     return prod
  1158.  
  1159. producer_cb = callsback(producer_cb)
  1160.  
  1161. def get_snurl(url):
  1162.     return get_short_url(url, 'snurl')
  1163.  
  1164.  
  1165. def get_isgd(url):
  1166.     return get_short_url(url, 'isgd')
  1167.  
  1168.  
  1169. def get_tinyurl(url):
  1170.     return get_short_url(url, 'tinyurl')
  1171.  
  1172.  
  1173. class UrlShortener(object):
  1174.     endpoint = None
  1175.     
  1176.     def shorten(self, url):
  1177.         
  1178.         try:
  1179.             resp = urllib2.urlopen(UrlQuery(self.endpoint, d = self.get_args(url.encode('utf-8'))))
  1180.         except urllib2.HTTPError:
  1181.             e = None
  1182.             resp = e
  1183.  
  1184.         return self.process_response(resp)
  1185.  
  1186.     
  1187.     def get_args(self, url):
  1188.         raise NotImplementedError
  1189.  
  1190.     
  1191.     def process_response(self, resp):
  1192.         if resp.code != 200:
  1193.             body = resp.read()
  1194.             raise Exception(body)
  1195.         
  1196.         ret = resp.read()
  1197.         return ret
  1198.  
  1199.  
  1200.  
  1201. class isgd_shortener(UrlShortener):
  1202.     endpoint = 'http://is.gd/api.php'
  1203.     
  1204.     def get_args(self, url):
  1205.         return dict(longurl = url)
  1206.  
  1207.  
  1208.  
  1209. class tinyurl_shortener(UrlShortener):
  1210.     endpoint = 'http://tinyurl.com/api-create.php'
  1211.     
  1212.     def get_args(self, url):
  1213.         return dict(url = url)
  1214.  
  1215.  
  1216.  
  1217. class snipr_shortener(UrlShortener):
  1218.     endpoint = 'http://snipr.com/site/snip'
  1219.     
  1220.     def get_args(self, url):
  1221.         return dict(r = 'simple', link = url.encode('url'))
  1222.  
  1223.     
  1224.     def process_response(self, resp):
  1225.         ret = UrlShortener.process_response(self, resp)
  1226.         if not ret.startswith('http'):
  1227.             raise Exception('bad url', ret)
  1228.         
  1229.         return ret
  1230.  
  1231.  
  1232. _shorteners = {
  1233.     'snipr': snipr_shortener,
  1234.     'snurl': snipr_shortener,
  1235.     'snipurl': snipr_shortener,
  1236.     'isgd': isgd_shortener,
  1237.     'tinyurl': tinyurl_shortener,
  1238.     'tiny': tinyurl_shortener }
  1239.  
  1240. def get_short_url(url, provider = 'snipr'):
  1241.     shortener = _shorteners.get(provider)
  1242.     if shortener is None:
  1243.         raise Exception('UrlShortener provider %r not found', provider)
  1244.     
  1245.     return shortener().shorten(url)
  1246.  
  1247. if __name__ == '__main__':
  1248.     print get_snurl('http://www.google.com')
  1249.  
  1250.